<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>熔融氯化钠微观动态模拟</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            color: #333;
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
            padding: 20px;
            min-height: 100vh;
        }
        .container {
            max-width: 1100px;
            margin: 0 auto;
            background-color: white;
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
            overflow: hidden;
        }
        header {
            background: linear-gradient(to right, #2c3e50, #4a6491);
            color: white;
            padding: 25px;
            text-align: center;
        }
        h1 {
            font-size: 2.2rem;
            margin-bottom: 10px;
        }
        .subtitle {
            font-size: 1.1rem;
            opacity: 0.9;
        }
        .content {
            display: flex;
            flex-wrap: wrap;
            padding: 20px;
        }
        .simulation-section {
            flex: 3;
            min-width: 300px;
            padding: 15px;
        }
        .controls-section {
            flex: 2;
            min-width: 250px;
            padding: 15px;
            background-color: #f8f9fa;
            border-radius: 10px;
            margin-left: 10px;
        }
        .simulation-container {
            position: relative;
            width: 100%;
            height: 450px;
            border: 2px solid #e1e5eb;
            border-radius: 10px;
            background-color: #0a192f;
            overflow: hidden;
            box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.3);
        }
        .control-group {
            margin-bottom: 25px;
            padding: 15px;
            background-color: white;
            border-radius: 8px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
        }
        h2 {
            color: #2c3e50;
            margin-bottom: 15px;
            font-size: 1.4rem;
            border-bottom: 2px solid #eaecef;
            padding-bottom: 8px;
        }
        .temperature-control {
            display: flex;
            flex-direction: column;
            gap: 15px;
        }
        .slider-container {
            display: flex;
            align-items: center;
            gap: 15px;
        }
        input[type="range"] {
            flex: 1;
            height: 8px;
            border-radius: 5px;
            background: linear-gradient(to right, #3498db, #e74c3c);
            outline: none;
            -webkit-appearance: none;
        }
        input[type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 22px;
            height: 22px;
            border-radius: 50%;
            background: #2c3e50;
            cursor: pointer;
            border: 3px solid white;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
        }
        .temperature-display {
            font-size: 1.8rem;
            font-weight: bold;
            text-align: center;
            padding: 10px;
            border-radius: 8px;
            background-color: #f1f8ff;
            color: #2c3e50;
            transition: all 0.3s ease;
        }
        .btn-group {
            display: flex;
            gap: 10px;
            margin-top: 15px;
        }
        button {
            flex: 1;
            padding: 12px;
            border: none;
            border-radius: 6px;
            background-color: #3498db;
            color: white;
            font-weight: bold;
            cursor: pointer;
            transition: all 0.3s ease;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
        }
        button:hover {
            background-color: #2980b9;
            transform: translateY(-2px);
            box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
        }
        button:active {
            transform: translateY(0);
        }
        #resetBtn {
            background-color: #e74c3c;
        }
        #resetBtn:hover {
            background-color: #c0392b;
        }
        .state-indicator {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
            margin-top: 15px;
        }
        .state-dot {
            width: 15px;
            height: 15px;
            border-radius: 50%;
            background-color: #3498db;
        }
        .state-text {
            font-weight: bold;
            color: #2c3e50;
        }
        .legend {
            display: flex;
            justify-content: center;
            gap: 25px;
            margin-top: 15px;
        }
        .legend-item {
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .legend-color {
            width: 20px;
            height: 20px;
            border-radius: 50%;
        }
        .legend-na {
            background-color: #ff6b6b;
            box-shadow: 0 0 8px #ff6b6b;
        }
        .legend-cl {
            background-color: #4ecdc4;
            box-shadow: 0 0 8px #4ecdc4;
        }
        .info-panel {
            margin-top: 25px;
            padding: 20px;
            background-color: #f8f9fa;
            border-radius: 10px;
            border-left: 5px solid #3498db;
        }
        .info-panel h3 {
            color: #2c3e50;
            margin-bottom: 15px;
        }
        .info-panel ul {
            padding-left: 20px;
        }
        .info-panel li {
            margin-bottom: 10px;
        }
        .particle {
            position: absolute;
            border-radius: 50%;
            transition: all 0.3s ease;
        }
        .sodium {
            background: radial-gradient(circle at 30% 30%, #ff8a8a, #ff5252);
            box-shadow: 0 0 15px rgba(255, 107, 107, 0.7);
        }
        .chloride {
            background: radial-gradient(circle at 30% 30%, #7fffd4, #40e0d0);
            box-shadow: 0 0 15px rgba(78, 205, 196, 0.7);
        }
        .crystal-lattice {
            position: absolute;
            width: 100%;
            height: 100%;
            opacity: 0.2;
            pointer-events: none;
        }
        .lattice-line {
            position: absolute;
            background-color: rgba(52, 152, 219, 0.3);
        }
        @media (max-width: 768px) {
            .content {
                flex-direction: column;
            }
            .controls-section {
                margin-left: 0;
                margin-top: 20px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>熔融氯化钠微观动态模拟</h1>
            <p class="subtitle">观察温度变化对氯化钠晶体结构的影响</p>
        </header>
        
        <div class="content">
            <section class="simulation-section">
                <h2>微观粒子模拟</h2>
                <div class="simulation-container" id="simulation">
                    <!-- 晶体网格背景 -->
                    <div class="crystal-lattice" id="crystalLattice"></div>
                    <!-- 粒子将通过JavaScript动态生成 -->
                </div>
                <div class="legend">
                    <div class="legend-item">
                        <div class="legend-color legend-na"></div>
                        <span>钠离子 (Na⁺)</span>
                    </div>
                    <div class="legend-item">
                        <div class="legend-color legend-cl"></div>
                        <span>氯离子 (Cl⁻)</span>
                    </div>
                </div>
            </section>
            
            <section class="controls-section">
                <div class="control-group">
                    <h2>温度控制</h2>
                    <div class="temperature-control">
                        <div class="slider-container">
                            <span>低温</span>
                            <input type="range" id="temperatureSlider" min="25" max="1500" value="25" step="25">
                            <span>高温</span>
                        </div>
                        <div class="temperature-display" id="tempDisplay">25°C</div>
                        <div class="state-indicator">
                            <div class="state-dot" id="stateDot"></div>
                            <div class="state-text" id="stateText">固态晶体</div>
                        </div>
                    </div>
                </div>
                
                <div class="control-group">
                    <h2>模拟控制</h2>
                    <div class="btn-group">
                        <button id="startBtn">开始模拟</button>
                        <button id="pauseBtn">暂停模拟</button>
                        <button id="resetBtn">重置模拟</button>
                    </div>
                </div>
                
                <div class="info-panel">
                    <h3>教学说明</h3>
                    <ul>
                        <li><strong>红色粒子</strong>：钠离子(Na⁺)</li>
                        <li><strong>青色粒子</strong>：氯离子(Cl⁻)</li>
                        <li><strong>固态晶体</strong>：粒子排列有序，在晶格位置振动</li>
                        <li><strong>熔融状态</strong>：粒子运动加剧，晶格结构瓦解，离子自由移动</li>
                        <li><strong>导电性</strong>：熔融状态下，自由移动的离子使氯化钠能够导电</li>
                    </ul>
                    <p style="margin-top: 10px;"><strong>注意：</strong>氯化钠的熔点为801°C。当温度达到熔点时，晶体结构瓦解，形成熔融态。</p>
                </div>
            </section>
        </div>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const simulation = document.getElementById('simulation');
            const crystalLattice = document.getElementById('crystalLattice');
            const temperatureSlider = document.getElementById('temperatureSlider');
            const tempDisplay = document.getElementById('tempDisplay');
            const stateDot = document.getElementById('stateDot');
            const stateText = document.getElementById('stateText');
            const startBtn = document.getElementById('startBtn');
            const pauseBtn = document.getElementById('pauseBtn');
            const resetBtn = document.getElementById('resetBtn');
            
            let particles = [];
            let animationId;
            let isRunning = true;
            const particleCount = 72; // 粒子数量
            const containerWidth = simulation.offsetWidth;
            const containerHeight = simulation.offsetHeight;
            
            // 创建紧密排列的氯化钠晶体
            function createParticles() {
                simulation.innerHTML = '';
                particles = [];
                
                // 创建晶体网格背景
                createCrystalLattice();
                
                // 计算行和列
                const rows = 6;
                const cols = 6;
                const spacingX = containerWidth / (cols + 1);
                const spacingY = containerHeight / (rows + 1);
                
                // 创建紧密排列的晶体结构
                for (let row = 0; row < rows; row++) {
                    for (let col = 0; col < cols; col++) {
                        // 交替创建钠离子和氯离子
                        const isSodium = (row + col) % 2 === 0;
                        
                        // 创建粒子
                        const particle = document.createElement('div');
                        particle.className = `particle ${isSodium ? 'sodium' : 'chloride'}`;
                        
                        // 设置粒子大小
                        const size = isSodium ? 24 : 36; // 氯离子稍大
                        particle.style.width = `${size}px`;
                        particle.style.height = `${size}px`;
                        
                        // 计算位置 - 紧密排列
                        const x = (col + 1) * spacingX;
                        const y = (row + 1) * spacingY;
                        
                        // 设置初始位置
                        particle.style.left = `${x - size/2}px`;
                        particle.style.top = `${y - size/2}px`;
                        
                        simulation.appendChild(particle);
                        
                        particles.push({
                            element: particle,
                            x: x,
                            y: y,
                            vx: 0,
                            vy: 0,
                            isSodium: isSodium,
                            size: size,
                            originalX: x,
                            originalY: y,
                            // 添加随机速度，用于熔融状态
                            randomSpeed: Math.random() * 0.5 + 0.5
                        });
                    }
                }
            }
            
            // 创建晶体网格背景
            function createCrystalLattice() {
                crystalLattice.innerHTML = '';
                const rows = 6;
                const cols = 6;
                const spacingX = containerWidth / (cols + 1);
                const spacingY = containerHeight / (rows + 1);
                
                // 创建垂直线
                for (let col = 0; col <= cols; col++) {
                    const line = document.createElement('div');
                    line.className = 'lattice-line';
                    line.style.left = `${(col + 0.5) * spacingX}px`;
                    line.style.top = '0';
                    line.style.width = '1px';
                    line.style.height = '100%';
                    crystalLattice.appendChild(line);
                }
                
                // 创建水平线
                for (let row = 0; row <= rows; row++) {
                    const line = document.createElement('div');
                    line.className = 'lattice-line';
                    line.style.left = '0';
                    line.style.top = `${(row + 0.5) * spacingY}px`;
                    line.style.width = '100%';
                    line.style.height = '1px';
                    crystalLattice.appendChild(line);
                }
            }
            
            // 更新模拟
            function updateSimulation() {
                const temperature = parseInt(temperatureSlider.value);
                const normalizedTemp = (temperature - 25) / 1475; // 归一化温度 (25-1500°C)
                
                // 更新状态指示器
                updateStateIndicator(temperature);
                
                // 更新晶体网格透明度
                const latticeOpacity = Math.max(0, 0.3 - normalizedTemp * 0.5);
                crystalLattice.style.opacity = latticeOpacity;
                
                // 完全熔融状态判断
                const isFullyMolten = temperature > 1000;
                
                particles.forEach(particle => {
                    // 根据温度计算运动幅度
                    const amplitude = normalizedTemp * 40;
                    const frequency = 0.02 + normalizedTemp * 0.08;
                    
                    // 计算振动
                    const time = Date.now() * 0.001;
                    const vibrationX = Math.sin(time * frequency + particle.originalX * 0.1) * amplitude;
                    const vibrationY = Math.cos(time * frequency + particle.originalY * 0.1) * amplitude;
                    
                    // 高温时增加随机运动
                    let randomX = 0;
                    let randomY = 0;
                    
                    // 完全熔融状态下，粒子完全自由移动
                    if (isFullyMolten) {
                        // 使用更复杂的随机运动算法
                        randomX = (Math.random() - 0.5) * normalizedTemp * 40 * particle.randomSpeed;
                        randomY = (Math.random() - 0.5) * normalizedTemp * 40 * particle.randomSpeed;
                        
                        // 添加粒子间的排斥力
                        particles.forEach(otherParticle => {
                            if (particle !== otherParticle) {
                                const dx = particle.x - otherParticle.x;
                                const dy = particle.y - otherParticle.y;
                                const distance = Math.sqrt(dx * dx + dy * dy);
                                
                                if (distance < 50) {
                                    const force = 200 / (distance * distance);
                                    randomX += (dx / distance) * force;
                                    randomY += (dy / distance) * force;
                                }
                            }
                        });
                        
                        // 更新粒子速度
                        particle.vx = particle.vx * 0.95 + randomX * 0.05;
                        particle.vy = particle.vy * 0.95 + randomY * 0.05;
                        
                        // 更新位置
                        particle.x += particle.vx;
                        particle.y += particle.vy;
                    } 
                    // 部分熔融状态
                    else if (temperature > 800) {
                        randomX = (Math.random() - 0.5) * normalizedTemp * 25;
                        randomY = (Math.random() - 0.5) * normalizedTemp * 25;
                        
                        // 更新位置，但仍受原始位置的一定约束
                        particle.x = particle.originalX + vibrationX + randomX;
                        particle.y = particle.originalY + vibrationY + randomY;
                    }
                    // 固态
                    else {
                        particle.x = particle.originalX + vibrationX;
                        particle.y = particle.originalY + vibrationY;
                    }
                    
                    // 边界检查
                    if (particle.x < particle.size/2) {
                        particle.x = particle.size/2;
                        if (isFullyMolten) particle.vx *= -0.5;
                    }
                    if (particle.x > containerWidth - particle.size/2) {
                        particle.x = containerWidth - particle.size/2;
                        if (isFullyMolten) particle.vx *= -0.5;
                    }
                    if (particle.y < particle.size/2) {
                        particle.y = particle.size/2;
                        if (isFullyMolten) particle.vy *= -0.5;
                    }
                    if (particle.y > containerHeight - particle.size/2) {
                        particle.y = containerHeight - particle.size/2;
                        if (isFullyMolten) particle.vy *= -0.5;
                    }
                    
                    // 应用位置
                    particle.element.style.left = `${particle.x - particle.size/2}px`;
                    particle.element.style.top = `${particle.y - particle.size/2}px`;
                    
                    // 根据温度调整粒子透明度（表示热运动）
                    const opacity = 0.7 + normalizedTemp * 0.3;
                    particle.element.style.opacity = opacity;
                    
                    // 高温时增加粒子发光效果
                    if (temperature > 800) {
                        const glowIntensity = 0.5 + normalizedTemp * 0.5;
                        if (particle.isSodium) {
                            particle.element.style.boxShadow = `0 0 ${10 + glowIntensity * 10}px rgba(255, 107, 107, ${0.5 + glowIntensity * 0.5})`;
                        } else {
                            particle.element.style.boxShadow = `0 0 ${10 + glowIntensity * 10}px rgba(78, 205, 196, ${0.5 + glowIntensity * 0.5})`;
                        }
                    } else {
                        // 固态时恢复原始发光效果
                        if (particle.isSodium) {
                            particle.element.style.boxShadow = `0 0 15px rgba(255, 107, 107, 0.7)`;
                        } else {
                            particle.element.style.boxShadow = `0 0 15px rgba(78, 205, 196, 0.7)`;
                        }
                    }
                });
                
                if (isRunning) {
                    animationId = requestAnimationFrame(updateSimulation);
                }
            }
            
            // 更新状态指示器
            function updateStateIndicator(temperature) {
                if (temperature < 600) {
                    stateDot.style.backgroundColor = '#3498db';
                    stateText.textContent = '固态晶体';
                    stateText.style.color = '#3498db';
                } else if (temperature < 800) {
                    stateDot.style.backgroundColor = '#e67e22';
                    stateText.textContent = '接近熔点';
                    stateText.style.color = '#e67e22';
                } else if (temperature < 1000) {
                    stateDot.style.backgroundColor = '#e74c3c';
                    stateText.textContent = '熔融状态';
                    stateText.style.color = '#e74c3c';
                } else {
                    stateDot.style.backgroundColor = '#ff4757';
                    stateText.textContent = '完全熔融';
                    stateText.style.color = '#ff4757';
                }
            }
            
            // 温度变化处理
            temperatureSlider.addEventListener('input', function() {
                const temp = this.value;
                tempDisplay.textContent = `${temp}°C`;
                
                // 更新温度显示颜色
                if (temp < 600) {
                    tempDisplay.style.color = '#3498db';
                } else if (temp < 800) {
                    tempDisplay.style.color = '#e67e22';
                } else if (temp < 1000) {
                    tempDisplay.style.color = '#e74c3c';
                } else {
                    tempDisplay.style.color = '#ff4757';
                }
            });
            
            // 开始模拟
            startBtn.addEventListener('click', function() {
                if (!isRunning) {
                    isRunning = true;
                    updateSimulation();
                }
            });
            
            // 暂停模拟
            pauseBtn.addEventListener('click', function() {
                isRunning = false;
                if (animationId) {
                    cancelAnimationFrame(animationId);
                }
            });
            
            // 重置模拟
            resetBtn.addEventListener('click', function() {
                temperatureSlider.value = 25;
                tempDisplay.textContent = '25°C';
                tempDisplay.style.color = '#3498db';
                createParticles();

                updateStateIndicator(25);
            });
            
            // 初始化
            createParticles();
            updateSimulation();
        });
    </script>
</body>
</html>